/*
 * TCSS 422 - Spring quarter 2011
 * Team: 	Googlers
 * Members: Deepa Sahni, Krisnil Gounder, Michael Schweiger
 * Date: 	April 25, 2011
 */
package ui;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import main.Main;
import web.Gatherer2;

/**
 * A console based output reporter object to report data that is given to it.  Any objects
 * are reported via toString method, so if a custom message is requested, embed the
 * entire message into a new String and give this the new string.
 * @author Michael Schweiger
 * @version 1.0
 */
public class ConsoleReporter extends Reporter {

	/**
	 * Stores the file to write to.
	 */
	private final File my_file;
	
	/**
	 * Stores the FileWriter used for saving.
	 */
	private final FileWriter my_writer;
	
	/**
	 * The count of pages that have actually been displayed.
	 */
	private int reported_count = 0;
	
	/**
	 * Accepts a file to write to also, cannot be null.
	 * @param the_file The file to write to.  File should already be instantiated.
	 */
	public ConsoleReporter(final File the_file) throws IllegalArgumentException,IOException {
		super();
		if (the_file == null) {
			throw new IllegalArgumentException("File cannot be null!");
		}
		my_file = the_file;
		my_writer = new FileWriter(my_file);
	}
	
	/**
	 * Stops the reporting, closes the log file if applicable.
	 */
	public void stop() {
		super.stop();
		if (my_writer != null) {
			try {
				my_writer.close();
			} catch (IOException e) {
				//ignore
			}
		}
	}
	
	/**
	 * Default, outputs to console without writing to a file.
	 */
	public ConsoleReporter() {
		my_file = null;
		my_writer = null;
	};
	
	/**
	 * The total parsing time taken so far.
	 */
	private long parsing_time_taken = 0L;

	/**
	 * Continually displays the data that has been given to it.  Data is displayed in
	 * the order given.
	 */
	 @SuppressWarnings("unchecked")
	public void display() throws IllegalStateException {
		while (hasMoreData() && reported_count < Main.MAX_PAGES) {
			reported_count++;
			Object next = getNextObject();
			if (!(next instanceof List)) {
				throw new IllegalStateException("Data is in improper format!");
			}
			List<Object> next_list = (List<Object>) next;
			if (next_list.size() != 3) {
				throw new IllegalStateException("Data list doesn't have 3 elements");
			}
			
			Object temp = next_list.remove(0);
			if (!(temp instanceof String)) {
				throw new IllegalStateException("First element of data isn't String");
			}
			String URL = (String) temp;
			
			temp = next_list.remove(0);
			if (!(temp instanceof Map)) {
				throw new IllegalStateException("Second element of data isn't Map");
			}
			Map<String, Long> header_data = (HashMap<String, Long>) temp;
			
			temp = next_list.remove(0);
			if (!(temp instanceof Map)) {
				throw new IllegalStateException("Third element of data isn't Map");
			}
			Map<String, Integer> term_data = (HashMap<String, Integer>) temp;
			
			long time_taken = header_data.get(Gatherer2.TIME_TAKEN_FOR_PAGE);
			long pages = reported_count;
			long words = header_data.get(Gatherer2.TOTAL_WORDS_SCANNED);
			long links = header_data.get(Gatherer2.TOTAL_LINKS_SCANNED);
			
			parsing_time_taken += time_taken;
			
			StringBuilder builder = new StringBuilder();
			builder.append("Parsed: " + URL + "\n");
			builder.append("Pages Retrieved: " + pages + "\n");
			builder.append("Average words per page: " + ((int) (words / pages))
					+ "\n");
			builder.append("Average URLS per page: " + ((int) (links / pages))
					+ "\n");
			//Put formatted term info here
			builder.append(String.format("%1$-25s %2$-20s %3$-10s", 
					"Keyword", "Avg. hits per page", "Total hits") + "\n");
			for (String term : term_data.keySet()) {
				int total_hits = term_data.get(term);
				double avg_hits = total_hits / (double) pages;
				
				builder.append("     ");
				builder.append(String.format("%1$-20s %2$-20.3f %3$-10d", 
						term, avg_hits, total_hits) + "\n");
			}
			builder.append("\n");
			builder.append("Page limit: " + Main.MAX_PAGES + "\n");
			builder.append("Average parse time per page: " + 
					String.format("%1$d", (long) (parsing_time_taken / pages)) +
					" ms\n");
			builder.append("Total running time: " + 
					String.format("%1$.3f", (System.currentTimeMillis() - 
							Main.INITIAL_TIME) / 1000.0) +
							" sec \n");
			String output = builder.toString() + "\n";
			System.out.println(builder.toString() + "\n");
			try {
				saveFile(output);
			} catch (IOException e) {
				System.err.println("Error saving to the file " +
						my_file.getAbsolutePath() + "\n");
			}
			Main.increaseReportedCount();
		}
	}
	
	/**
	 * This method stores the data in a text file.
	 * 
	 * @author Krisnil Gounder
	 * @version April 21st, 2011
	 * 
	 */
	 private void saveFile(String append) throws IOException {
		 if(my_writer != null) {
			 my_writer.write(append);
		 }
	 }
}
